package cn.kgc.springday01.factory;

import cn.kgc.springday01.anotations.Auto;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.ResourceBundle;
import java.util.Set;

/**
 * @author 课工场
 * @date 2023/10/6
 * @description 使用工厂模式解决代码耦合问题
 */
public class BeanFactory {

    // 初始化容器  存储对象
    private static HashMap<String, Object> beans = new HashMap<String, Object>();

    static {
        // 创建在bean.properties 文件中声明的实例对象   存储在  beans集合中
        ResourceBundle bean = ResourceBundle.getBundle("bean");
        // 获取所有的key
        Set<String> keys = bean.keySet();

        // 遍历所有的key  创建对象
        for (String key : keys) {
            //获取配置文件中key对应的value
            String clazzName = (String) bean.getObject(key);
            //  通过反射创建对象
            try {
                Class<?> clazz = Class.forName(clazzName);
                //获取无参构造
                Constructor<?> declaredConstructor = clazz.getDeclaredConstructor();
                // 通过无参构造方法 创建实例对象
                Object o = declaredConstructor.newInstance();
                // 将创建完成的对象 保存在  beans集合中
                beans.put(key, o);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        //  通过工厂来维护对象之间的依赖关系
        Set<String> mapKey = beans.keySet();
        for (String mKey : mapKey) {

            // 获取容器中key对应的实例对象  解析对象中是否含有需要初始化的属性 @Auto
            Object o = beans.get(mKey);
            //  通过实例对象 获取类对象
            Class<?> clazz = o.getClass();
            // 通过类对象 解析类中所有的属性
            Field[] declaredFields = clazz.getDeclaredFields();

            // 遍历数组  判定属性中是够含有 @Auto注解
            if (declaredFields != null) {
                for (Field declaredField : declaredFields) {
                    //  判定属性中是否含有 @Auto注解
                    Auto annotation = declaredField.getAnnotation(Auto.class);
                    if (annotation != null) {
                        // 获取属性名字
                        String name = declaredField.getName();
                        // 从map集合中获取和当前对象属性名字一致的key对应的value
                        Object o1 = beans.get(name);
                        try {
                            // 提升私有属性的操作权限
                            declaredField.setAccessible(true);
                            //  有注解   赋值
                            declaredField.set(o, o1);
                        } catch (IllegalAccessException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        }


    }

//    public static EmpDao getEmpDao(){
//
//        return new EmpDaoNewImpl();
//    }

    public static Object getObject(Class clazz) {
        // 反射   创建对象
        try {
            Constructor declaredConstructor = clazz.getDeclaredConstructor();
            Object o = declaredConstructor.newInstance();
            return o;
        } catch (Exception e) {
            System.out.println(e);
        }
        return null;
    }


    public static Object getBean(String beanName) {

        return beans.get(beanName);
    }


    public static <T> T getBean(String beanName, Class<T> clazz) {
        Object o = beans.get(beanName);
        return clazz.cast(o);
    }

}
